235. 二叉搜索树的最近公共祖先

235. 二叉搜索树的最近公共祖先

Similar Question

leading to the advanced question

Solution Tips

方案一: Common Path

var lowestCommonAncestor = function(root, p, q) {
    // 找 path , path 里的公共部分就是共同的祖先, 找到最先的那个
    // find all path, if both found, break;
    // 然后还需要再按照 path
    const stack = [root];
    const pathStack = [[root]];
    let pPath = [];
    let qPath = [];

    while (stack.length) {
        const node = stack.pop();
        const curPath = pathStack.pop();

        if (node) {
            if (node.val === p.val) {
                pPath = curPath;
            }

            if (node.val === q.val) {
                qPath = curPath;
            }

            if (node.left) {
                stack.push(node.left);
                const newPath = [...curPath, node.left]
                pathStack.push(newPath);
            }
            if (node.right) {
                stack.push(node.right);
                const newPath = [...curPath, node.right]
                pathStack.push(newPath);
            }
        }
    }

    // 找出 pPath 和 curPath 的公共部分
    const commonPath = [];
    for (let i = 0; i < pPath.length; i++) {
        if (pPath[i]?.val === qPath[i]?.val) {
            commonPath.push(pPath[i]);
        }
        else {
            break;
        }
    }

    return commonPath[commonPath.length - 1]
};

方案二: 利用 BST 性质

如果 curVal 大于两者, 说明一定都在左子树, 所以公共祖先也一定在左子树

类似的, 如果小于, 则是一定都在右子树.

并且, 有且仅有一个节点可以做到, 一个大于, 一个小于, 这个节点就是两者的最近的公共祖先

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        List<TreeNode> path_p = getPath(root, p);
        List<TreeNode> path_q = getPath(root, q);
        TreeNode ancestor = null;
        for (int i = 0; i < path_p.size() && i < path_q.size(); ++i) {
            if (path_p.get(i) == path_q.get(i)) {
                ancestor = path_p.get(i);
            } else {
                break;
            }
        }
        return ancestor;
    }

    public List<TreeNode> getPath(TreeNode root, TreeNode target) {
        List<TreeNode> path = new ArrayList<TreeNode>();
        TreeNode node = root;
        while (node != target) {
            path.add(node);
            if (target.val < node.val) {
                node = node.left;
            } else {
                node = node.right;
            }
        }
        path.add(node);
        return path;
    }
}